package com.niit.scala

import scala.io.StdIn

/**
 * Date:2025/3/7
 * Author：Ys
 * Description:
 *  总结：
 *      1.三引号：如果有大段的文本信息，就可以使用三引号就行保存。三引号所保存的字符串的格式信息：换行 空格
 *      2.惰性赋值，当有一些自定义的常量数据较大的时候，而这些数据并不是马上去加载到JVM内存当中，就可以用使用惰性赋值提高效率
 *        格式 ： lazy val 变量名 = 值
 *      3.标识符就是给变量、方法、类起名字，Scala和Java中的标识符非常相似
 *         命名规则：
 *            必须以以字母、下划线开头，后面可以接字母、数字、下划线、美元符号
 *            不能以数字开头
 *            不能和Scala关键字重名
 *            最好做到见名知意
 *         命名规范：
 *            小驼峰命名法：首字母小写，后面每个单词首字母大写，比如：helloWorld 命名 变量 方法
 *            大驼峰命名法：首字母大写，后面每个单词首字母大写，比如：HelloWorld 命名 类或者特质
 *            包：全部小写
 *       4.数据类型:
 *          1.数值类型：
 *              Byte:8位有符号整数，范围：-128~127
 *              Short:16位有符号整数，范围：-32768~32767
 *              Int:32位有符号整数，范围：-2147483648~2147483647
 *              Long:64位有符号整数，范围：-9223372036854775808~9223372036854775807
 *              Float:32位浮点数，范围：-3.4028235E38~3.4028235E38
 *              Double:64位浮点数，范围：-1.7976931348623157E308~1.7976931348623157E308
 *              Char:16位无符号整数，范围：0~65535
 *              Boolean:true/false
 *             定义变量可以不用写类型，让编译器自动推断
 *             整型默认是Int,浮点型默认是Double
 *             Any是所有类型的父类，相当于Java中的Object类
 *        5.类型转换：
 *          自动数据类型转换： 用大数据类型去装小的数据类型
 *          强制数据类型转换：用小的数据类型去装大数据类型
 *          var/val 变量名:数据类型 = 数值.toXxx （Xxx:要转换的数据类型）
 *        6.键盘录入：：
 *          数值键盘录入： StdIn.readInt()/StdIn.readDouble()/StdIn.readLong()/StdIn.readByte()/StdIn.readShort()
 *          字符串键盘录入： StdIn.readLine()
 *        7.算数运算符：
 *          加减乘除：+ - * /
 *          取余：%
 *          取整：/
 *          幂：^
 *          赋值：=
 *          自增自减：++ --
 *          比较运算符：
 *              == 等于
 *              != 不等于
 *              > 大于
 *              < 小于
 *              >= 大于等于
 *              <= 小于等于
 *          逻辑运算符：
 *              && 与 || 或 !非
 *          赋值运算符：
 *              += -= *= /= %=
 *        8.顺序结构：程序按照从上至下，从左至右的顺序依次逐行执行，中间没有任何跳转和跳转。
 *        9.分支结构：程序按照条件进行分支，然后按照从上至下，从左至右的顺序依次逐行执行，中间有跳转。
 *          if-else if-else
 *          Scala中是没有三目运算符的，替换方案val res = if(2>1) 2 else 1
 *        10.循环结构：程序按照循环进行执行，然后按照从上至下，从左至右的顺序依次逐行执行，中间有跳转。
 */
object Base03 {

  def main(args: Array[String]): Unit = {
    //1.三引号： ‘’ 字符  “” 字符串  “”“：如果有大段的文本信息，就可以使用三引号就行保存。三引号所保存的字符串信息同样保存格式
    val str1 = "123456" +
                  "789"
    println(str1)
    val str2 =
      """
        |123
        |456
        |789
        |""".stripMargin
    println(str2)
    //2.惰性赋值。当使用惰性赋值的时候，该变量用到时候才会加载到内存当中。格式： lazy val 变量名 = 值
    lazy val name = "张三"
    println(name)

    //3.数值类型转换。 自动数据类型转换： 用大数据类型去装小的数据类型
    //  从小到大的数据类型依次为：Byte -> Short -> Int -> Long -> Float -> Double
    var a:Int = 10
    var b:Long = a
    var c:Double = 3 + 3.14
    println(a,b,c)
    //强制数据类型转换：用小的数据类型去装大数据类型
    //将范围大的数据类型通过一定格式转换为范围小的数据类型(可能会造成精度的损失)
    // var/val 变量名:数据类型 = 数值.toXxx （Xxx:要转换的数据类型）
    val d:Double = 5.21
    val e:Int = d.toInt
    println(e)
    //String类型 转换成 值类型
    //var/val 变量名:数据类型 = 数值.toXxx （Xxx:要转换的数据类型）
    val f:String = "123"
    println(f.toInt)
    val g:Int = 123
    println(g + "") // 任意类型对字符串的拼接，都会自动转换为字符串类型
    println(g.toString)

    //4.键盘录入
    // 字符串的键盘录入： StdIn.readLine()
    // 数值的键盘录入： StdIn.readInt()/StdIn.readDouble()/StdIn.readLong()/StdIn.readByte()/StdIn.readShort()
    println("请输入你们最大愿望：")
    //val str = StdIn.readLine();
   // println(s"我的最大愿望是：${str}")

    //5.余数
    var q = 27 % 5  // 27 - 27/5 * 5 = 27 - 25 = 2
    println(q)

    b += a  // b = b + a
    println(b)

    var w = "abc".eq("efg")
    println(w)

    //6.逻辑运算符 &&与  ||或  ! 非
    println( 1>2 && 2 > 1) //false
    println(2 > 0 && 11>8)//true

    println(1>2 || 2>1)// true
    println(2>0 || 11>8)//true

    println(!(1>2) || 2>1)//true
    println(!( 1>2 || 2>1 ))//false


    //7.if-else if -else
    val score = 80
    if (score >= 90 && score <= 100) {
      println("你很优秀")
    } else if (score >= 80 && score < 90) {
      println("一般般")
    } else if (score >= 0 && score < 80) {
      println("努力吧你")
    } else {
      println("成绩无效")
    }

    //8.三目(元)运算符 int a =2>1?2:1
    //Scala中是没有三目运算符，替换方案：val res = if(2>1) 2 else 1
    val res = if (2 > 1) 2 else 1
    println(res)

    //9.代码块 块表达式
    //代码块表达式的格式  val  a  = { 代码} 。 注意：代码块中最后一句代码是返回指。
    val kuai = {
      if (2 > 1) {
        println("成立了")
      }
      1 + 1
      3 + 3
      4 + 4 // 最后一条语句才是最后的返回值
    }
    println(kuai)

    /*
    10. for 循环
    格式：for(i <- 表达式/集合)
     需求：循环输出1-10
     */
    for (i <- 1 to 10) {
      println(i)
    }
    val num = 1 to 10 //[1,2,3,4,5,6,7,8,9,10]
    for (i <- num) {
      println("Hello Scala")
    }
    /*
    11. for循环的守卫，for表达式中，可以添加if判断语句，这个if判断称之为守卫。
       格式：for(i <- 表达式/集合 if 条件)
       利用守卫，输出1-10中，偶数 对二取余数，余数等于0就是偶数
     */
    for (i <- 1 to 10 if i % 2 == 0) {
      println(i)
    }
    /*
    12.for推导式
      for循环也是有返回值的，可以使用yield关键字，来返回for循环的结果。结果一般是一个集合
     */
    val v = for (i <- 1 to 10) yield i * 10
    println(v) //v = [10,20,30,40,50,60,70,80,90,100]
    /*
     13.while 和 do-while
       需求：输出10次Hello World
     */
    var count = 1
    while (count <= 10) {
      println("Hello World")
      count += 1
    }
    do {
      println("Hello World")
      count -= 1
    } while (count >= 1)

    /*
    14.break 和 continue 。 注意：Scala中是没有continue
       Scala要想使用break需要在for循环外面嵌套一条 breakable
       import scala.util.control.Breaks.{break,breakable}
     */
    import scala.util.control.Breaks.{break, breakable}
    breakable {
      for (i <- 1 to 10) {
        if (i == 5) {
          break()
        }
        println("break", i)
      }

    }
    //需求：用for 打印 1-10。但是不能输出能被2整除的数字
    for (i <- 1 to 10) {
      breakable {
        if (i % 2 == 0) {
          break()
        } else {
          println("continue", i)
        }
      }
    }

   /*
   15.方法
       def 方法名(参数名:参数类型,参数名:参数类型):[返回值类型] = {}
      注意： 参数列表的参数类型不能省略的
           返回值类型可以省略，由Scala编译器自动推断
           返回值可以不写return,默认就是块表达式的值
    */
    val max = getMax(b=1,a=2)
    println(max)

    val sum = getSum(1,2,3,4,5,6,7)
    println(sum)
  }

  //定义一个求两个数的最大值的方法
  //默认参数：参数列表中，如果参数有默认值，那么该参数就是可选参数。如果没有实际参数的时，默认使用默认值。a=6 b=7
  //带名参数：在传入实参的时候指定给哪个形参传值
  def getMax(a:Int=6,b:Int=7):Int={
     if (a>b) a else b
  }
  //优化写法
  def getMax2(a:Int,b:Int) = if (a>b) a else b

  /*
   变长参数：如果方法的参数是不固定的，可以将该方法的参数声明为可变参数。
    def 方法名(参数名:参数类型*):返回值类型 = {
        方法体
    }
   */
   def getSum(a:Int*)={
     a.sum
   }
}
